
/*
 * Copyright 2014 Щекотова Ангелина Александровна.
 * Этот файл — часть J4JClientServer Framework
 * J4JClientServer Framework - свободная программа: вы можете перераспространять ее и/или изменять
 * ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде, в каком
 * она была опубликована Фондом свободного программного обеспечения; либо
 * версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
 *
 * J4JClientServer Framework распространяется в надежде, что она будет полезной,
 * но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
 * или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
 * общественной лицензии GNU.
 *
 * Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
 * вместе с этой программой. Если это не так, см.
 * <http://www.gnu.org/licenses/>.
 */

package ru.java4java.utils;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Config {
    private static final Log log = LogFactory.getLog(Config.class);

    private static String propertiesFilePath = "config.properties";

    private static final Pattern PARAMETRIZATION_PATTERN = Pattern.compile("\\$\\{(.*?)\\}");
    private static Properties config = readParameterizedPropertiesFile(new File(propertiesFilePath));

    public static Properties getProperties() {
        return (Properties)config.clone();
    }

    public static String getTestPropertiesFilePath() {
        return propertiesFilePath;
    }

    public static void setTestPropertiesFilePath(String _propertiesFilePath) {
        config = readParameterizedPropertiesFile(new File(_propertiesFilePath));
        propertiesFilePath = _propertiesFilePath;
    }

    public static void updateConfig(Map<String, String> config) {
        for (String key: config.keySet()) {
            Config.config.setProperty(key, config.get(key));
        }
    }

    public static Pattern getPattern(String key, String defaultValue) {
        String result = config.getProperty(key, defaultValue);
        return Pattern.compile(result);
    }

    public static String getString(String key) {
        return getString(key, "");
    }

    public static String getString(String key, String defaultValue) {
        return config.getProperty(key, defaultValue);
    }

    public static void setString(String key, String value) {
        config.setProperty(key.trim(), value.trim());
    }

    public static boolean getBoolean(String key) {
        return getBoolean(key, false);
    }

    public static boolean getBoolean(String key, boolean defaultValue) {
        String result = config.getProperty(key, Boolean.toString(defaultValue));
        return Boolean.valueOf(result);
    }

    public static int getInteger(String key) {
        return getInteger(key, 0);
    }

    public static int getInteger(String key, int defaultValue) {
        int result;
        try {
            result = Integer.parseInt(config.getProperty(key, Integer.toString(defaultValue)));
        } catch (NumberFormatException e) {
            return defaultValue;
        }
        return result;
    }

    public static long getLong(String key) {
        return getLong(key, 0);
    }

    public static long getLong(String key, long defaultValue) {
        long result;
        try {
            result = Long.parseLong(config.getProperty(key, Long.toString(defaultValue)));
        } catch (NumberFormatException e) {
            return defaultValue;
        }
        return result;
    }

    public static Map<String,String> getStringsByPrefix(String prefix) {
        Map<String,String> result = new HashMap<String,String>();
        Set<Object> keys = config.keySet();
        for (Object objectKey : keys) {
            if (!(objectKey instanceof String)) {
                continue;
            }
            String key = (String)objectKey;
            if (key.equals(prefix) || key.startsWith(prefix+".")) {
                result.put(key, getString(key));
            }
        }
        return result;
    }

    public static String[] getStringArray(String key) {
        return getString(key).split(",");
    }

    public static Properties readParameterizedPropertiesFile(File propertiesFile) {
        Properties p = new Properties();
        BufferedReader lines = null;
        if (!propertiesFile.exists()) {
            log.debug("'" + propertiesFile.getAbsolutePath() + "' file has not been found");
            return p;
        }
        try {
            lines = new BufferedReader(new InputStreamReader(new FileInputStream(propertiesFile),"UTF-8"));
            String line;
            while ((line=lines.readLine())!=null) {
                line = line.trim();
                if (line.startsWith("#") || line.length()==0) continue; // Comment
                Matcher m = PARAMETRIZATION_PATTERN.matcher(line);
                StringBuffer resultLine = new StringBuffer();
                while (m.find()) {
                    String key = m.group(1);
                    String replacement;
                    replacement = p.getProperty(key);
                    if (replacement == null) {
                        replacement = "";
                    }
                    replacement = replacement.replace("\\","\\\\\\\\").replace("$", "\\$");
                    m.appendReplacement(resultLine, replacement);
                }
                m.appendTail(resultLine);
                line = resultLine.toString();
                //p.load(new StringReader(line)); //java6
                String[] keyAndValue = line.split("[=|:]",2);
                if (keyAndValue.length!=2) keyAndValue = line.split("[ |\t|\f]",2);
                if (keyAndValue.length<2) continue;
                p.put(keyAndValue[0].trim(),keyAndValue[1].trim());
            }
        } catch (IOException e) {
            log.fatal("Failed to read properties file: "+propertiesFile.getName(), e);
            throw new RuntimeException("IOException", e);
        } finally {
            ClosingUtils.close(lines);
        }
        return p;
    }

}
